home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / AX25USER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  5.5 KB  |  244 lines

  1. /* User interface subroutines for AX.25
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #ifdef AX25
  6. #include "mbuf.h"
  7. #include "timer.h"
  8. #include "iface.h"
  9.  
  10. #if !defined(_lint)
  11. static char rcsid[] OPTIONAL = "$Id: ax25user.c,v 1.12 1997/08/19 01:19:22 root Exp root $";
  12. #endif
  13.  
  14. void reset_all_ax25 (void);
  15.  
  16.  
  17. /* Open an AX.25 connection */
  18. struct ax25_cb *
  19. open_ax25 (iface, local, theremote, mode, window, r_upcall, t_upcall, s_upcall, user)
  20. struct iface *iface;        /* Interface */
  21. char *local;            /* Local address */
  22. char *theremote;        /* theremote address */
  23. int mode;            /* active/passive/server */
  24. int16 window;            /* Window size in bytes */
  25. void (*r_upcall) (struct ax25_cb *, int);    /* Receiver upcall handler */
  26. void (*t_upcall) (struct ax25_cb *, int);    /* Transmitter upcall handler */
  27. void (*s_upcall) (struct ax25_cb *, int, int);    /* State-change upcall handler */
  28. int user;            /* User linkage area */
  29. {
  30. struct ax25_cb *axp;
  31. char remtmp[AXALEN];
  32.  
  33.     if (theremote == NULLCHAR) {
  34.         theremote = remtmp;
  35.         (void) setcall (theremote, " ");
  36.     }
  37.     if ((axp = find_ax25 (local, theremote, iface)) != NULLAX25 && axp->state != LAPB_DISCONNECTED)
  38.         return NULLAX25;/* Only one to a customer */
  39.     if (axp == NULLAX25 && (axp = cr_ax25 (local, theremote, iface)) == NULLAX25)
  40.         return NULLAX25;
  41.  
  42.     axp->iface = iface;
  43.     axp->window = window;
  44.     axp->r_upcall = r_upcall;
  45.     axp->t_upcall = t_upcall;
  46.     axp->s_upcall = s_upcall;
  47.     axp->user = user;
  48.  
  49.     switch (mode) {
  50.         case AX_SERVER:
  51.             axp->flags.clone = 1;
  52.             /* fall through */
  53.         case AX_PASSIVE:    
  54.             axp->state = LAPB_LISTEN;
  55.             return axp;
  56.         case AX_ACTIVE:
  57.         default:
  58.             break;
  59.     }
  60.     switch (axp->state) {
  61.         case LAPB_DISCONNECTED:
  62.             est_link (axp);
  63.             lapbstate (axp, LAPB_SETUP);
  64.             break;
  65.         case LAPB_SETUP:
  66.             free_q (&axp->txq);
  67.             break;
  68.         case LAPB_RECOVERY:
  69.         case LAPB_CONNECTED:
  70.             free_q (&axp->txq);
  71.             est_link (axp);
  72.             lapbstate (axp, LAPB_SETUP);
  73.             break;
  74.         case LAPB_DISCPENDING:    /* Ignore */
  75.         default:
  76.             break;
  77.     }
  78.     return axp;
  79. }
  80.  
  81.  
  82. /* Send data on an AX.25 connection. Caller provides optional PID. If
  83.  * a PID is provided, then operate in stream mode, i.e., a large packet
  84.  * is automatically packetized into a series of paclen-sized data fields.
  85.  *
  86.  * If pid == -1, it is assumed the packet (which may actually be a queue
  87.  * of distinct packets) already has a PID on the front and it is passed
  88.  * through directly even if it is very large.
  89.  */
  90. int
  91. send_ax25 (axp, bp, pid)
  92. struct ax25_cb *axp;
  93. struct mbuf *bp;
  94. int pid;
  95. {
  96. struct mbuf *bp1;
  97. int16 offset, len, size;
  98.  
  99.     if (axp == NULLAX25 || bp == NULLBUF) {
  100.         free_p (bp);
  101.         return -1;
  102.     }
  103.     if (pid != -1) {
  104.         offset = 0;
  105.         len = len_p (bp);
  106.         /* It is important that all the pushdowns be done before
  107.          * any part of the original packet is freed.
  108.          * Otherwise the pushdown might erroneously overwrite
  109.          * a part of the packet that had been duped and freed.
  110.          */
  111.         while (len != 0) {
  112.             size = min (len, axp->paclen);
  113.             (void) dup_p (&bp1, bp, offset, size);
  114.             len -= size;
  115.             offset += size;
  116.             bp1 = pushdown (bp1, 1);
  117.             bp1->data[0] = uchar(pid);
  118.             enqueue (&axp->txq, bp1);
  119.         }
  120.         free_p (bp);
  121.     } else {
  122.         enqueue (&axp->txq, bp);
  123.     }
  124.     return lapb_output (axp);
  125. }
  126.  
  127.  
  128. /*lint -esym(18,recv_ax25) */
  129. /* Receive incoming data on an AX.25 connection */
  130. struct mbuf *
  131. recv_ax25 (struct ax25_cb *axp, int16 cnt)
  132. {
  133. struct mbuf *bp;
  134.  
  135.     if (axp->rxq == NULLBUF)
  136.         return NULLBUF;
  137.  
  138.     if (cnt == 0) {
  139.         /* This means we want it all */
  140.         bp = axp->rxq;
  141.         axp->rxq = NULLBUF;
  142.     } else {
  143.         bp = ambufw (cnt);
  144.         bp->cnt = pullup (&axp->rxq, bp->data, cnt);
  145.     }
  146.     /* If this has un-busied us, send a RR to reopen the window */
  147.     if (len_p (axp->rxq) < axp->window
  148.         && (len_p (axp->rxq) + bp->cnt) >= axp->window)
  149.         (void) sendctl (axp, LAPB_RESPONSE, RR);
  150.  
  151.     return bp;
  152. }
  153.  
  154.  
  155. /* Close an AX.25 connection */
  156. int
  157. disc_ax25 (axp)
  158. struct ax25_cb *axp;
  159. {
  160.     if (axp == NULLAX25)
  161.         return -1;
  162.     switch (axp->state) {
  163.         case LAPB_LISTEN:
  164.             del_ax25 (axp);
  165.             break;
  166.         case LAPB_DISCPENDING:
  167.             lapbstate (axp, LAPB_DISCONNECTED);
  168.             break;
  169.         case LAPB_CONNECTED:
  170.         case LAPB_RECOVERY:
  171.             free_q (&axp->txq);
  172.             axp->retries = 0;
  173.             (void) sendctl (axp, LAPB_COMMAND, DISC | PF);
  174.             stop_timer (&axp->t3);
  175.             start_timer (&axp->t1);
  176.             lapbstate (axp, LAPB_DISCPENDING);
  177.             break;
  178.         case LAPB_DISCONNECTED:
  179.         default:
  180.             break;    /* Ignored */
  181.     }
  182.     return 0;
  183. }
  184.  
  185.  
  186. /* Verify that axp points to a valid ax25 control block */
  187. int
  188. ax25val (axp)
  189. struct ax25_cb *axp;
  190. {
  191. register struct ax25_cb *axp1;
  192.  
  193.     if (axp == NULLAX25)
  194.         return 0;    /* Null pointer can't be valid */
  195.     for (axp1 = Ax25_cb; axp1 != NULLAX25; axp1 = axp1->next)
  196.         if (axp1 == axp)
  197.             return 1;
  198.     return 0;
  199. }
  200.  
  201.  
  202. /* Force a retransmission */
  203. int
  204. kick_ax25 (axp)
  205. struct ax25_cb *axp;
  206. {
  207.     if (!ax25val (axp))
  208.         return -1;
  209.     recover (axp);
  210.     return 0;
  211. }
  212.  
  213.  
  214. /* Abruptly terminate an AX.25 connection */
  215. int
  216. reset_ax25 (axp)
  217. struct ax25_cb *axp;
  218. {
  219.     void (*upcall) (struct ax25_cb *, int);
  220.  
  221.     if (axp == NULLAX25)
  222.         return -1;
  223.     /* Be nice and send a DM - WG7J */
  224.     (void) disc_ax25 (axp);
  225.     upcall = (void (*)(struct ax25_cb *, int)) axp->s_upcall;
  226.     lapbstate (axp, LAPB_DISCONNECTED);
  227.     /* Clean up if the standard upcall isn't in use */
  228.     if (upcall != (void (*)(struct ax25_cb *, int)) s_ascall)
  229.         del_ax25 (axp);
  230.     return 0;
  231. }
  232.  
  233.  
  234.  
  235. /* Display AX.25 link level control blocks */
  236. void
  237. reset_all_ax25 (void)
  238. {
  239.     while (Ax25_cb != NULLAX25)
  240.         (void) reset_ax25 (Ax25_cb);
  241. }
  242.  
  243. #endif
  244.